//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <core.h>
#include <init.h>
#include <_hal.h>
#include <_schedule.h>
#include "recycle.h"
#include <mdetect.h>
#include <kmemdet.h>
#include <eladbg.h>

KernelState g_kernelState = KernelState_Chaos;

KrnGlobals krn = {
    KERNEL_BASE,        // vaKernelVirtBase

    KCONFIG_TICKRATE    // uTickRate
};

STATIC DECL_CODEINIT void ParseBootCommandLine();
STATIC DECL_CODEINIT void PrintLogo();

#ifdef _arm
EXTERN_C DECL_CODEINIT void CDECL __KernelSetup(
        physaddr_t paKernelPhysBase, physaddr_t paKernelImagePhysBase,
        physaddr_t paMemoryMappedIoBase, physaddr_t paMemoryMappedIoLimit,
        int reserved1, int reserved2)
#else
EXTERN_C DECL_CODEINIT void CDECL KrnSetup(
        physaddr_t paKernelPhysBase, physaddr_t paKernelImagePhysBase,
        physaddr_t paMemoryMappedIoBase, physaddr_t paMemoryMappedIoLimit,
        int reserved1, int reserved2)
#endif
{
    TESTENTRY_KERNEL_SETUP

    SetupCPU();

#ifdef _mips
    ChatInit();

    InitCache();
#endif

    SetupMMU(
        paKernelPhysBase, paKernelImagePhysBase,
        paMemoryMappedIoBase, paMemoryMappedIoLimit);

    SetupCRT();

    STAT_INIT

    KMEM_INIT

    g_kernelState = KernelState_Setup;
}

EXTERN_C DECL_CODEINIT bool_t CDECL KrnInitialize()
{
    TESTENTRY_KERNEL_INITIALIZE

    if (KernelState_Setup != g_kernelState) return FALSE;

    ParseBootCommandLine();

    if (!InitInterrupts())      return FALSE;

    if (!InitGdbStub())         return FALSE;

    if (!InitThread0())         return FALSE;

    if (!InitHAT())             return FALSE;

    ELADBG_INITIALIZE

    g_kernelState = KernelState_Initialize;

    return TRUE;
}

EXTERN_C void CDECL MantleEntry(void);

STATIC Int32 InitThreadRoutine(void *pvParameter);

STATIC void Thread0Routine();

EXTERN_C DECL_CODEINIT void CDECL KrnStartup()
{
    TESTENTRY_KERNEL_STARTUP

    assert(KernelState_Initialize == g_kernelState);

    g_kernelState = KernelState_Startup;

    PrintLogo();

    SwitchToThread0();
}

EXTERN_C DECL_CODEINIT void KernelStartup2()
{
#if !(defined(_mips) && defined(_EVC))
DECL_ASMENTRY(Thread0Startup)
#endif

    verify(InitPhysicalMemory());

    verify(InitMantle());

    verify(InitCrust());

    verify(InitTime());

    verify(InitPeriodicTasks());

    verify(InitThreads());

    verify(InitSchedule());

    verify(StartPeriodicTasks());

    MDETECT_INIT

    Thread0Routine();
}

STATIC void Thread0Routine()
{
    Thread *pThread = CreateSystemThread(
        &InitThreadRoutine, NULL,
        g_pDefaultScheduleClass, g_uDefaultSchedulePolicy);
    if (NULL != pThread) pThread->Release();

    uint32_t uFlags = SaveFlagsAndCli();
    GetThread0()->m_uPrivilegedProcessorTicks = 0;
    RestoreIF(uFlags);

    while (TRUE) {
        BspIdle();
    }
}

STATIC DECL_CODEINIT void ParseBootCommandLine()
{
}

STATIC DECL_CODEINIT void PrintLogo()
{
    kputs("\n"
         "Elastos RTOS version 2.1"
#if     defined(_OPTIMIZE)
         " [optimize build]"
#elif   defined(_DEBUG)
         " [debug build]"
#endif
         "\n"
         "Copyright(C) 2000-2007, Elastos, Inc., All Rights Reserved.\n\n");
}

STATIC Int32 InitThreadRoutine(void *pvParameter)
{
    verify(InitDrivers());

    verify(RecycleAll());

    MantleEntry();

    return 0;
}
